/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
 *
 */
import {expect} from '@jest/globals';
import {iconv} from '@ohos/hvigor';
import * as execa from 'execa';
import fse from 'fs-extra';
import path from 'path';
import {runHvigorAsync} from '../../common/common';
import {resourcesPath} from '../../plugins//common-fun';
import {commonConfig} from '../../plugins/common-config';
import {
  AbilityType,
  APIType,
  APIVersion,
  CaseLevel,
  LanguageType,
  ModuleTemplateType,
  RuntimeOSType,
  SDKType
} from '../../plugins/project-builder/models/constants';
import {TestCaseBuilder} from '../../plugins/task-builder/task-case-builder';
import {ProjectBuildOption, TestCaseFun} from '../../plugins/task-builder/test-case';
import {TestTaskOptionBuilder} from '../../plugins/task-builder/test-task-option';

const projectBuilderOption: ProjectBuildOption = {
  template: {
    sdk: SDKType.Single,
    runtimeOS: RuntimeOSType.HarmonyOS,
    apiVersion: APIVersion.API11,
    apiType: APIType.STAGE,
    language: LanguageType.ArkTs,
    abilityType: AbilityType.Application,
    entryTemplateType: ModuleTemplateType.EmptyAbility
  }
};

const testfun: TestCaseFun = async (project, taskConfig, record) => {
  const projectRootPath = project.projectRootPath();
  const libraryPath = path.resolve(projectRootPath, 'staticlibrary');
  const entryPath = project.getModule('entry').moduleRootPath();
  await fse.copy(path.resolve(resourcesPath, 'extra/staticlibrary'), libraryPath);
  const moduleFile = await fse.readFile(`${projectRootPath}/build-profile.json5`);

  // 去掉文件中多余的 ,
  const str = iconv.decode(moduleFile, 'utf-8').replace(/(,[\r\n]\s+[}|\]])/g, ($1) => $1.slice(1));

  const moduleObj = JSON.parse(str);
  moduleObj.modules.push({
    name: 'staticlibrary',
    srcPath: './staticlibrary',
  });
  // 配置工程级collectAllLibs为true
  moduleObj.app.products[0].buildOption = {
    nativeLib: {
      collectAllLibs: true
    }
  };

  await fse.writeFile(`${projectRootPath}/build-profile.json5`, JSON.stringify(moduleObj, null, 2), 'utf-8');
  const libraryMain = path.resolve(libraryPath, 'src/main');
  await fse.ensureFile(`${libraryMain}/module.json5`);
  await fse.writeFile(`${libraryMain}/module.json5`, JSON.stringify({
    module: {
      name: 'staticlibrary',
      type: 'har',
      deviceTypes: [
        'phone',
        'tablet'
      ]
    }
  }, null, 2), 'utf-8');

  // har模块配置headerPath
  const moduleFileHar = await fse.readFile(`${libraryPath}/build-profile.json5`);
  const strHar = iconv.decode(moduleFileHar, 'utf-8').replace(/(,[\r\n]\s+[}|\]])/g, ($1) => $1.slice(1));

  const moduleObjHar = JSON.parse(strHar);
  // 配置工程级collectAllLibs为true
  moduleObjHar.buildOption.nativeLib = {
    headerPath: ['./src/main/cpp/include', './src/main/cpp/include2']
  };

  await fse.writeFile(`${libraryPath}/build-profile.json5`, JSON.stringify(moduleObjHar, null, 2), 'utf-8');

  await fse.ensureDir(`${libraryMain}/cpp`)
  await fse.ensureDir(`${libraryMain}/cpp/include`)
  await fse.ensureDir(`${libraryMain}/cpp/include2`)
  await fse.ensureFile(`${libraryMain}/cpp/include/c.h`)
  await fse.ensureFile(`${libraryMain}/cpp/include/c.cpp`)
  await fse.ensureFile(`${libraryMain}/cpp/include/c2.h`)
  await fse.ensureFile(`${libraryMain}/cpp/include/c2.cpp`)

  // 在json5中添加依赖har
  const jsonPath = path.resolve(entryPath, 'oh-package.json5');
  const jsonBuffer = await fse.readFile(jsonPath);
  const jsonData = JSON.parse(iconv.decode(jsonBuffer, 'utf-8'));
  jsonData.dependencies['har'] = 'file:../staticlibrary';
  await fse.writeFile(jsonPath, JSON.stringify(jsonData,null,2), 'utf-8');

  // 执行ohpm install
  const install = await execa.command(commonConfig.ohpmInstallCommand, {
    cwd: entryPath
  });
  record.addStep('entry install', install);
  // 2. sync一下，避免执行clean
  const syncCommand = '--sync -p product=default --analyze=normal --parallel --incremental --no-daemon'.split(' ');
  await runHvigorAsync(project.projectRootPath(), syncCommand);

  // 执行hap构建
  const commonCommand = '--mode module -p product=default assembleHap --analyze=normal --parallel --incremental --daemon'.split(' ');
  const result = await runHvigorAsync(project.projectRootPath(), commonCommand);
  expect(result.stdout).toContain('BUILD SUCCESSFUL');

  // 单独构建har
  const commonCommandHar = '--mode module -p product=default -p module=staticlibrary@default assembleHar --analyze=normal --parallel --incremental --no-daemon'.split(' ');
  const resultHar = await runHvigorAsync(project.projectRootPath(), commonCommandHar);
  expect(resultHar.stdout).toContain('BUILD SUCCESSFUL');
  // 解析entry的hap包
  const outputDir =
      await parse(path.resolve(libraryPath, 'build/default/outputs/default/staticlibrary.har'));
  expect(fse.existsSync(path.resolve(outputDir, 'package/include', 'c.h'))).toEqual(true);
  expect(fse.existsSync(path.resolve(outputDir, 'package/include', 'c.cpp'))).toEqual(true);
  expect(fse.existsSync(path.resolve(outputDir, 'package/include', 'c2.h'))).toEqual(true);
  expect(fse.existsSync(path.resolve(outputDir, 'package/include', 'c2.cpp'))).toEqual(true);
}


/**
 * 解析har包
 * @param {string} hqfPath hap包的绝对路径
 * @returns {Promise<string>} 解析的产物目录
 */
async function parse(hqfPath: string) {
  const dir = path.dirname(hqfPath);
  let fileName = path.basename(hqfPath);
  fileName = fileName.replace(fileName.slice(-3), 'tgz');
  const zipPath = path.resolve(dir, fileName);

  // 将生成的xxx包复制为zip包
  fse.copyFileSync(hqfPath, zipPath);
  // 解压zip，解析出生成hap里的内容
  const outputDir = zipPath.slice(0, -18);
  // 通过命令行解压tgz
  await execa.command(`tar zxvf ${zipPath} -C ${outputDir}`);
  return outputDir;
}

TestCaseBuilder.builder()
  .caseName('HEADERPATH_E2E_TEST')
  .description('headerPath支持配置多个头文件路径')
  .projectBuilderOption(projectBuilderOption)
  .taskConfig(TestTaskOptionBuilder.builder().caseLevel(CaseLevel.AR).build())
  .testFun(testfun)
  .load();
